package com.samehope.ar.service.impl;

import com.samehope.ar.constant.RoleNameEnum;
import com.samehope.ar.dto.FindPasswordParam;
import com.samehope.ar.dto.ModifyPasswordParam;
import com.samehope.ar.dto.UpdateUserInfoParam;
import com.samehope.ar.dto.UserRegisterParam;
import com.samehope.ar.entity.SysRole;
import com.samehope.ar.entity.SysUser;
import com.samehope.ar.entity.SysUserRole;
import com.samehope.ar.mapper.SysUserMapper;
import com.samehope.ar.service.ISysRoleService;
import com.samehope.ar.service.ISysUserRoleService;
import com.samehope.ar.service.ISysUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.samehope.ar.util.*;
import com.samehope.ar.vo.UserCompanyDataVO;
import com.samehope.ar.vo.UserInfoVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author Zhang Luo
 * @since 2019-12-23
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    @Autowired
    private ISysUserRoleService userRoleService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    private HttpServletRequest request;

    /**
     * 根据手机号查找用户
     * @param mobile
     * @return
     */
    @Override
    public SysUser getByMobile(String mobile) {
        return this.baseMapper.getByMobile(mobile);
    }

    /**
     * 根据用户查找权限集合
     * @param userId
     * @return
     */
    @Override
    public List<SysRole> getRoleListByUser(Long userId) {
        return this.baseMapper.getRoleListByUserAndCompanyAndProject(userId,
                SessionUtil.getCompanyId(), SessionUtil.getProjectId());
    }

    /**
     * 用户注册
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void register(UserRegisterParam param) {

        String code = RedisUtil.get(param.getMobile());
        if (code == null || !code.equals(param.getCode())) {
            throw new IllegalArgumentException("验证码错误");
        }

        SysUser user = this.baseMapper.getByMobile(param.getMobile());
        if (user != null && user.getStatus() == 1) {
            throw new IllegalArgumentException("该手机号码已被注册");
        }

        if (user == null) {
            user = new SysUser();
        }
        user.setMobile(param.getMobile());
        user.setStatus(1);
        user.setPwd(passwordEncoder.encode(param.getPassword()));
        this.saveOrUpdate(user);

        SysRole sysRole = roleService.findByRoleName(RoleNameEnum.USER.getName());
        SysUserRole userRole = new SysUserRole();
        userRole.setUserId(user.getId());
        userRole.setRoleId(sysRole.getId());
        userRole.setCreateBy(user.getId());
        userRoleService.save(userRole);
    }

    /**
     * 用户登录
     * @param mobile
     * @param password
     * @return
     */
    @Override
    public UserCompanyDataVO login(String mobile, String password) {
        String token = null;
        UserCompanyDataVO userCompanyDataVO = null;
        //密码需要客户端加密后传递
        try {
            SysUser sysUser = this.baseMapper.getByMobile(mobile);
            if (sysUser == null) {
                throw new UsernameNotFoundException("用户名或密码错误");
            }

            if(!passwordEncoder.matches(password, sysUser.getPwd())){
                throw new BadCredentialsException("密码不正确");
            }

            sysUser.setLastLoginTime(DateUtils.toString(LocalDateTime.now()));
            sysUser.setLastLoginIp(IPUtils.getIpAddress(request));
            this.updateById(sysUser);

            userCompanyDataVO = this.baseMapper.findCompanyByUser(sysUser.getId());
            token = jwtTokenUtil.generateToken(sysUser);

            userCompanyDataVO.setToken(token);
            userCompanyDataVO.setTokenHead(tokenHead);
        } catch (AuthenticationException e) {
            log.error("登录异常:{}", e.getMessage());
        }
        return userCompanyDataVO;
    }

    /**
     * 刷新token
     * @param token
     * @return
     */
    @Override
    public String refreshToken(String token) {
        token = token.substring(tokenHead.length());
        if (jwtTokenUtil.canRefresh(token)) {
            return jwtTokenUtil.refreshToken(token);
        }
        return null;
    }

    /**
     * 找回密码功能
     * @param param
     */
    @Override
    public void findPassword(FindPasswordParam param) {
        String code = RedisUtil.get(param.getMobile());
        if (code == null || !param.getCode().equals(code)) {
            throw new IllegalArgumentException("验证码错误");
        }

        SysUser sysUser = this.baseMapper.getByMobile(param.getMobile());
        sysUser.setPwd(passwordEncoder.encode(param.getPassword()));
        sysUser.setUpdateBy(sysUser.getId());
        sysUser.setUpdateDate(LocalDateTime.now());
        this.updateById(sysUser);
    }

    /**
     * 修改密码功能
     * @param param
     */
    @Override
    public void modifyPassword(ModifyPasswordParam param) {
        SysUser sysUser = this.getById(SessionUtil.getUserId());

        if (!passwordEncoder.matches(param.getSrcPassword(), sysUser.getPwd())) {
            throw new IllegalArgumentException("原密码错误");
        }

        sysUser.setPwd(passwordEncoder.encode(param.getNewPassword()));
        sysUser.setUpdateBy(sysUser.getId());
        sysUser.setUpdateDate(LocalDateTime.now());
        this.updateById(sysUser);

    }

    /**
     * 修改个人资料
     * @param param
     */
    @Override
    public void updateUserInfo(UpdateUserInfoParam param) {
        SysUser sysUser = this.getById(param.getUserId());
        sysUser.setName(param.getName());
        sysUser.setContact(param.getContact());
        sysUser.setGender(param.getGender());
        sysUser.setEmail(param.getEmail());
        sysUser.setWechat(param.getWechat());
        sysUser.setUpdateBy(SessionUtil.getUserId());
        sysUser.setUpdateDate(LocalDateTime.now());
        this.updateById(sysUser);
    }

    /**
     * 查询个人资料
     * @return
     */
    @Override
    public UserInfoVO getUserInfo() {
        return this.baseMapper.getUserInfoByUserId(SessionUtil.getUserId());
    }
}
